package org.mathcloud.math.core.scilab.quantity;

import org.mathcloud.math.core.common.quantity.ComplexNumber;
import org.mathcloud.math.core.common.quantity.RealNumber;
import org.mathcloud.math.core.generic.signature.GenericQuantityObjectSignature;
import org.mathcloud.math.core.scilab.manager.ScilabSupervisor;
import org.scilab.modules.javasci.JavasciException;
import org.scilab.modules.types.ScilabDouble;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ScilabComplexNumber extends ScilabQuantityObject implements ComplexNumber
{
	public ScilabComplexNumber()
	{
		super();
		sciEngine = ScilabSupervisor.getScilabEngine();
		double [][]t = {{0.0}};
		sciObject = new ScilabDouble(t,t);
		try
		{
			sciEngine.put(sciVarName, sciObject);
		} catch (JavasciException e)
		{
			log.error("Constructor -", e);
		}		
		signature = GenericQuantityObjectSignature.getComplexNumberSignature();
		signature.setRealizationName("scilab");
	}

	public ScilabComplexNumber(double real, double image)
	{
		super();
		sciEngine = ScilabSupervisor.getScilabEngine();
		sciObject = new ScilabDouble(real,image);
		try
		{
			sciEngine.put(sciVarName, sciObject);
		} catch (JavasciException e)
		{
			log.error("Constructor - ",e);
		}		
		signature = GenericQuantityObjectSignature.getComplexNumberSignature();
		signature.setRealizationName("scilab");
	}

	public ScilabComplexNumber(RealNumber in)
	{
		super();
		sciEngine = ScilabSupervisor.getScilabEngine();
		double [][]t1 = {{in.getValue()}};
		double [][]t2 = {{0.0}};
		sciObject = new ScilabDouble(t1,t2);
		try
		{
			sciEngine.put(sciVarName, sciObject);
		} catch (JavasciException e)
		{
			log.error("Constructor - ",e);
		}				
		signature = GenericQuantityObjectSignature.getComplexNumberSignature();
		signature.setRealizationName("scilab");
	}

	public ScilabComplexNumber(ComplexNumber in)
	{
		super();
		sciEngine = ScilabSupervisor.getScilabEngine();
		double [][]t1 = {{in.getRealPart()}};
		double [][]t2 = {{in.getImagePart()}};
		sciObject = new ScilabDouble(t1,t2);
		sciVarName = "var_"+ScilabSupervisor.getVarId();
		try
		{
			sciEngine.put(sciVarName, sciObject);
		} catch (JavasciException e)
		{
			log.error("Constructor - ",e);
		}
		signature = GenericQuantityObjectSignature.getComplexNumberSignature();
		signature.setRealizationName("scilab");		
	}
	
	@Override
	public Double getArg()
	{ 
		String tmpVar = "tmp_"+ScilabSupervisor.getVarId();
		String sciJob;
		if ((getRealPart()!=0)&&(getImagePart()!=0))
			sciJob = tmpVar + "=" + "atan(imag("+getVarName()+")/real("+getVarName()+"));";
		else if (getRealPart()!=0)
			sciJob = tmpVar + "=" + "acos("+getVarName()+"/abs("+getVarName()+"))";
		else sciJob = tmpVar + "=" + "asin("+getVarName()+"/abs("+getVarName()+"))";
		if (sciEngine.exec(sciJob))
		{
			try
			{
				log.info(sciJob);
				ScilabDouble arg = (ScilabDouble)sciEngine.get(tmpVar);				
				sciJob = "clear "+tmpVar+";";
				if (sciEngine.exec(sciJob))
					log.info(sciJob);				
				return arg.getRealPart()[0][0];				
			} catch (JavasciException e)
			{
				log.error("Get arg - ",e);
				return null;
			}
		}
		else return null;
	}

	@Override
	public Double getImagePart()
	{
		if (sciObject!=null)
			try
			{
				sciEngine.put(getVarName(), sciObject);
				return sciObject.getImaginaryPart()[0][0];
			} catch (JavasciException e)
			{
				log.error("Get image part - ",e);
				return null;
			}
			else return null;
	}

	@Override
	public Double getMod()
	{
		String tmpVar = "tmp_"+ScilabSupervisor.getVarId();
		String sciJob;
		sciJob = tmpVar + "=" + "abs("+getVarName()+");";
		if (sciEngine.exec(sciJob))
		{
			try
			{
				log.info(sciJob);
				ScilabDouble arg = (ScilabDouble)sciEngine.get(tmpVar);				
				sciJob = "clear "+tmpVar+";";
				if (sciEngine.exec(sciJob))
					log.info(sciJob);				
				return arg.getRealPart()[0][0];				
			} catch (JavasciException e)
			{
				log.error("Get mod - ",e);
				return null;
			}
		}
		else return null;
	}

	@Override
	public Double getRealPart()
	{
		if (sciObject!=null)
			try
			{
				sciEngine.put(getVarName(), sciObject);
				return sciObject.getRealPart()[0][0];
			} catch (JavasciException e)
			{
				log.error("Get real part - ",e);
				return null;
			}
			else return null;
	}

	@Override
	public Double getValue()
	{
		return getMod();
	}

	@Override
	public void setRealPart(double arg0)
	{
		double real = arg0;
		double image = getImagePart();		
		sciObject = new ScilabDouble(real,image);
		try
		{
			log.info(getVarName()+"=complex("+real+","+image+");");
			sciEngine.put(getVarName(), sciObject);
		} catch (JavasciException e)
		{
			log.error("Set real part - ",e);
		}		
	}
	
	@Override
	public void setImagePart(double arg0)
	{
		double real = getRealPart();
		double image = arg0;		
		sciObject = new ScilabDouble(real,image);
		try
		{
			log.info(getVarName()+"=complex("+real+","+image+");");			
			sciEngine.put(getVarName(), sciObject);
		} catch (JavasciException e)
		{
			log.error("Set image part - ",e);
		}		
	}
	
	@Override
	public void setArg(double arg0)
	{
		double real = getMod()*Math.cos(arg0);
		double image = getMod()*Math.sin(arg0);
		sciObject = new ScilabDouble(real,image);
		try
		{		
			log.info(getVarName()+"=complex("+real+","+image+");");			
			sciEngine.put(getVarName(), sciObject);
		} catch (JavasciException e)
		{
			log.error("Set arg -",e);
		}		
	}


	@Override
	public void setMod(double arg0)
	{
		double real = arg0*Math.cos(getArg());
		double image = arg0*Math.sin(getArg());
		sciObject = new ScilabDouble(real,image);
		try
		{
			log.info(getVarName()+"=complex("+real+","+image+");");
			sciEngine.put(getVarName(), sciObject);
		} catch (JavasciException e)
		{
			log.error("Set mod -",e);
		}		
	}

	@Override
	public void setValue(double arg0)
	{
		setMod(arg0);		
	}
	
	private static final Logger log = LoggerFactory.getLogger(ScilabComplexNumber.class);
	
}
